home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
lib
/
c
/
stdio
/
RCS
/
vfprintf.c,v
< prev
next >
Wrap
Text File
|
1992-03-27
|
34KB
|
1,637 lines
head 1.20;
branch ;
access ;
symbols sprited:1.20.1;
locks ; strict;
comment @ * @;
1.20
date 91.08.27.17.35.55; author rab; state Exp;
branches 1.20.1.1;
next 1.19;
1.19
date 90.10.16.16.41.36; author shirriff; state Exp;
branches ;
next 1.18;
1.18
date 90.10.11.15.14.09; author shirriff; state Exp;
branches ;
next 1.17;
1.17
date 90.10.08.17.04.52; author shirriff; state Exp;
branches ;
next 1.16;
1.16
date 90.09.11.14.27.14; author kupfer; state Exp;
branches ;
next 1.15;
1.15
date 90.09.05.22.41.07; author shirriff; state Exp;
branches ;
next 1.14;
1.14
date 90.08.03.16.30.43; author shirriff; state Exp;
branches ;
next 1.13;
1.13
date 89.09.12.11.42.15; author douglis; state Exp;
branches ;
next 1.12;
1.12
date 89.08.04.16.05.13; author douglis; state Exp;
branches ;
next 1.11;
1.11
date 89.08.04.14.45.55; author douglis; state Exp;
branches ;
next 1.10;
1.10
date 89.07.28.15.57.35; author douglis; state Exp;
branches ;
next 1.9;
1.9
date 89.07.28.15.56.48; author rab; state Exp;
branches ;
next 1.8;
1.8
date 89.06.16.14.14.45; author ouster; state Exp;
branches ;
next 1.7;
1.7
date 89.05.25.05.50.03; author rab; state Exp;
branches ;
next 1.6;
1.6
date 89.05.17.14.32.46; author rab; state Exp;
branches ;
next 1.5;
1.5
date 88.10.23.15.39.51; author ouster; state Exp;
branches ;
next 1.4;
1.4
date 88.07.25.13.12.35; author ouster; state Exp;
branches ;
next 1.3;
1.3
date 88.07.21.09.36.16; author ouster; state Exp;
branches ;
next 1.2;
1.2
date 88.06.17.17.42.51; author ouster; state Exp;
branches ;
next 1.1;
1.1
date 88.06.10.16.23.36; author ouster; state Exp;
branches ;
next ;
1.20.1.1
date 91.12.02.20.04.36; author kupfer; state Exp;
branches ;
next ;
desc
@@
1.20
log
@Added a forward declaration for signbit.
@
text
@/*
* vfprintf.c --
*
* Source code for the "vfprintf" library procedure.
*
* Copyright 1988 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.19 90/10/16 16:41:36 shirriff Exp Locker: rab $ SPRITE (Berkeley)";
#endif not lint
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <varargs.h>
#include <math.h>
extern int signbit _ARGS_ ((int value));
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* The following defines the size of buffer needed to hold the ASCII
* digits for the largest floating-point number and the largest integer.
*/
#define CVT_DBL_BUF_SIZE 320
#define CVT_INT_BUF_SIZE 33
/*
*----------------------------------------------------------------------
*
* CvtUtoA --
*
* Convert a number from internal form to a sequence of
* ASCII digits.
*
* Results:
* The return value is a pointer to the ASCII digits representing
* i, and *lengthPtr will be filled in with the number of digits
* stored at the location pointed to by the return value. The
* return value points somewhere inside buf, but not necessarily
* to the beginning. Note: the digits are left null-terminated.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static char *
CvtUtoA(i, base, buf, lengthPtr, capsFlag)
register unsigned i; /* Value to convert. */
register int base; /* Base for conversion. Shouldn't be
* larger than 36. 2, 8, and 16
* execute fastest.
*/
register char *buf; /* Buffer to use to hold converted string.
* Must hold at least CVT_INT_BUF_SIZE bytes. */
int *lengthPtr; /* Number of digits is stored here. */
int capsFlag; /* 1 if want capital abcd... */
{
register char *p;
register char hexOffset = (capsFlag ? 'A': 'a')-'9'-1;
/*
* Handle a zero value specially.
*/
if (i == 0) {
buf[0] = '0';
buf[1] = 0;
*lengthPtr = 1;
return buf;
}
/*
* Build the string backwards from the end of the result array.
*/
p = &buf[CVT_INT_BUF_SIZE-1];
*p = 0;
switch (base) {
case 2:
while (i != 0) {
p -= 1;
*p = '0' + (i & 01);
i >>= 1;
}
break;
case 8:
while (i != 0) {
p -= 1;
*p = '0' + (i & 07);
i >>= 3;
}
break;
case 16:
while (i !=0) {
p -= 1;
*p = '0' + (i & 0xf);
if (*p > '9') {
*p += hexOffset;
}
i >>= 4;
}
break;
default:
while (i != 0) {
p -= 1;
*p = '0' + (i % base);
if (*p > '9') {
*p += hexOffset;
}
i /= base;
}
break;
}
*lengthPtr = (&buf[CVT_INT_BUF_SIZE-1] - p);
return p;
}
/*
*----------------------------------------------------------------------
*
* CvtFtoA --
*
* This procedure converts a double-precision floating-point
* number to a string of ASCII digits.
*
* Results:
* The characters at buf are modified to hold up to numDigits ASCII
* characters, followed by a null character. The digits represent
* the most significant numDigits digits of value, with the lowest
* digit rounded. The value at *pointPtr is modified to hold
* the number of characters in buf that precede the decimal point.
* A negative value of *pointPtr means zeroes must be inserted
* between the point and buf[0]. If value is negative, *signPtr
* is set to TRUE; otherwise it is set to FALSE. The return value
* is the number of digits stored in buf, which is either:
* (a) numDigits (if the number is so huge that all numDigits places are
* used before getting to the right precision level, or if
* afterPoint is -1)
* (b) afterPoint + *pointPtr (the normal case if afterPoint isn't -1)
* If there were no significant digits within the specified precision,
* then *pointPtr gets set to -afterPoint and 0 is returned.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
CvtFtoA(value, numDigits, afterPoint, pointPtr, signPtr, buf, fpError)
double value; /* Value to be converted. */
int numDigits; /* Maximum number of significant digits
* to generate in result. */
int afterPoint; /* Maximum number of digits to generate
* after the decimal point. If -1, then
* there there is no limit. */
int *pointPtr; /* Will be filled in with position of
* decimal point (number of digits before
* decimal point). */
int *signPtr; /* Modified to indicate whether or not
* value was negative. */
char *buf; /* Place to store ASCII digits. Must hold
* at least numDigits+1 bytes. */
int *fpError; /* pointer to flag that is set if the number
is not a valid number. */
{
register char *p;
double fraction, intPart;
int i, numDigits2;
char tmpBuf[CVT_DBL_BUF_SIZE];
/* Large enough to hold largest possible
* floating-point number.
*/
/*
* Take care of the sign.
*/
if (signbit(value)) {
*signPtr = TRUE;
value = -value;
} else {
*signPtr = FALSE;
}
/*
* Make sure the value is a valid number
*/
if (isinf(value)) {
/*
* Set the error flag so the invoking function will know
* that something is wrong.
*/
*fpError = TRUE;
strcpy(buf, "Inf");
return sizeof("Inf") - 1;
}
if (isnan(value)) {
*fpError = TRUE;
strcpy(buf, "NaN");
return sizeof("NaN") - 1;
}
*fpError = FALSE;
/*
* Divide value into an integer and a fractional component. Convert
* the integer to ASCII in a temporary buffer, then move the characters
* to the real buffer (since we're converting from the bottom up,
* we won't know the highest-order digit until last).
*/
fraction = modf(value, &intPart);
*pointPtr = 0;
for (p = &tmpBuf[CVT_DBL_BUF_SIZE-1]; intPart != 0; p -= 1) {
double tmp;
char digit;
tmp = modf(intPart/10.0, &intPart);
digit = (tmp * 10.0) + .2;
*p = digit + '0';
*pointPtr += 1;
}
p++;
for (i = 0; (i <= numDigits) && (p <= &tmpBuf[CVT_DBL_BUF_SIZE-1]);
i++, p++) {
buf[i] = *p;
}
/*
* If the value was zero, put an initial zero in the buffer
* before the decimal point.
*/
if (value == 0.0) {
buf[0] = '0';
i = 1;
*pointPtr = 1;
}
/*
* Now handle the fractional part that's left. Repeatedly multiply
* by 10 to get the next digit. At the beginning, the value may be
* very small, so do repeated multiplications until we get to a
* significant digit.
*/
if ((i == 0) && (fraction > 0)) {
while (fraction < .1) {
fraction *= 10.0;
*pointPtr -= 1;
};
}
/*
* Compute how many total digits we should generate, taking into
* account both numDigits and afterPoint. Then generate the digits.
*/
numDigits2 = afterPoint + *pointPtr;
if ((afterPoint < 0) || (numDigits2 > numDigits)) {
numDigits2 = numDigits;
}
for ( ; i <= numDigits2; i++) {
double tmp;
char digit;
fraction = modf(fraction*10.0, &tmp);
digit = tmp;
buf[i] = digit + '0';
}
/*
* The code above actually computed one more digit than is really
* needed. Use it to round the low-order significant digit, if
* necessary. This could cause rounding to propagate all the way
* back through the number.
*/
if ((numDigits2 >= 0) && (buf[numDigits2] >= '5')) {
for (i = numDigits2-1; ; i--) {
if (i < 0) {
int j;
/*
* Must slide the entire buffer down one slot to make
* room for a leading 1 in the buffer. Careful: if we've
* already got numDigits digits, must drop the last one to
* add the 1.
*/
for (j = numDigits2; j > 0; j--) {
buf[j] = buf[j-1];
}
if (numDigits2 < numDigits) {
numDigits2++;
}
(*pointPtr)++;
buf[0] = '1';
break;
}
buf[i] += 1;
if (buf[i] <= '9') {
break;
}
buf[i] = '0';
}
}
if (numDigits2 <= 0) {
numDigits2 = 0;
*pointPtr = -afterPoint;
}
buf[numDigits2] = 0;
return numDigits2;
}
/*
*----------------------------------------------------------------------
*
* vfprintf --
*
* This utility routine does all of the real work of printing
* formatted information. It is called by printf, fprintf,
* sprintf, vprintf, and vsprintf.
*
* Results:
* The return value is the total number of characters printed.
*
* Side effects:
* Information is output on stream. See the manual page entry
* for printf for details.
*
*----------------------------------------------------------------------
*/
int
vfprintf(stream, format, args)
register FILE *stream; /* Where to output formatted results. */
register char *format; /* Contains literal text and format control
* sequences indicating how args are to be
* printed. See the man page for details. */
va_list args; /* Variable number of values to be formatted
* and printed. */
{
int leftAdjust; /* TRUE means field should be left-adjusted. */
int minWidth; /* Minimum width of field. */
int precision; /* Precision for field (e.g. digits after
* decimal, or string length). */
int altForm; /* TRUE means value should be converted to
* an alternate form (depends on type of
* conversion). */
register char c; /* Current character from format string.
* Eventually it ends up holding the format
* type (e.g. 'd' for decimal). */
char pad; /* Pad character. */
char buf[CVT_DBL_BUF_SIZE+10];
/* Buffer used to hold converted numbers
* before outputting to stream. Must be
* large enough for floating-point number
* plus sign plus "E+XXX + null" */
char expBuf[CVT_INT_BUF_SIZE];
/* Buffer to use for converting exponents. */
char *signChar; /* This is the "+" or " " for the sign pos. */
char *prefix; /* Holds non-numeric stuff that precedes
* number, such as "-" or "0x". This is
* kept separate to be sure we add padding
* zeroes AFTER the prefix. */
register char *field; /* Pointer to converted field. */
int actualLength; /* Actual length of converted field. */
int point; /* Location of decimal point, for "f" and
* "e" conversions. */
int zeroPad; /* Zeros to pad number with. */
int sign; /* Also used for "f" and "e" conversions. */
int i, tmp;
int charsPrinted = 0; /* Total number of characters output. */
char *end;
int fpError = FALSE;
/*
* The main loop is to scan through the characters in format.
* Anything but a '%' is output directly to stream. A '%'
* signals the start of a format field; the formatting information
* is parsed, the next value from args is formatted and printed,
* and the loop goes on.
*/
for (c = *format; c != 0; format++, c = *format) {
if (c != '%') {
putc(c, stream);
charsPrinted += 1;
continue;
}
/*
* Parse off the format control fields.
*/
leftAdjust = FALSE;
pad = ' ';
minWidth = 0;
precision = -1;
altForm = FALSE;
signChar = "";
prefix = "";
actualLength = 0;
zeroPad = 0;
format++;
c = *format;
while (TRUE) {
if (c == '-') {
leftAdjust = TRUE;
} else if (c == '0') {
pad = '0';
} else if (c == '#') {
altForm = TRUE;
} else if (c == '+') {
signChar = "+";
} else if (c== ' ') {
if (!*signChar) {
signChar = " ";
}
} else {
break;
}
format++;
c = *format;
}
if (isdigit(c)) {
minWidth = strtoul(format, &end, 10);
format = end;
c = *format;
} else if (c == '*') {
minWidth = va_arg(args, int);
format++;
c = *format;
}
if (c == '.') {
format++;
c = *format;
precision = 0;
}
if (isdigit(c)) {
precision = strtoul(format, &end, 10);
format = end;
c = *format;
} else if (c == '*') {
precision = va_arg(args, int);
format++;
c = *format;
}
if (c == 'l') { /* Ignored for compatibility. */
format++;
c = *format;
}
if (c == 'h') { /* Ignored for compatibility. */
format++;
c = *format;
}
/*
* Take action based on the format type (which is now in c).
*/
field = buf;
switch (c) {
case 'D':
case 'd':
case 'i':
i = va_arg(args, int);
if (i < 0) {
prefix = "-";
i = -i;
actualLength = 1;
} else {
prefix = signChar;
actualLength = *prefix ? 1 : 0;
}
field = CvtUtoA((unsigned) i, 10, buf, &tmp, 0);
if (tmp < precision) {
zeroPad = precision-tmp;
}
actualLength += tmp+zeroPad;
break;
case 'O':
case 'o':
i = va_arg(args, int);
field = CvtUtoA((unsigned) i, 8, buf, &tmp, 0);
if (tmp < precision) {
zeroPad = precision-tmp;
}
if (altForm && (i != 0) && zeroPad==0) {
prefix = "0";
actualLength = 1;
}
actualLength += tmp+zeroPad;
break;
case 'X':
case 'x':
case 'p':
i = va_arg(args, int);
field = CvtUtoA((unsigned) i, 16, buf, &actualLength, c=='X');
if (actualLength < precision) {
zeroPad = precision-actualLength;
actualLength += zeroPad;
}
if (altForm) {
char *p;
if (c == 'X') {
if (i != 0) {
prefix = "0X";
actualLength += 2;
}
for (p = field; *p != 0; p++) {
if (*p >= 'a') {
*p += 'A' - 'a';
}
}
} else if (i != 0) {
prefix = "0x";
actualLength += 2;
}
}
break;
case 'U':
case 'u':
field = CvtUtoA(va_arg(args, unsigned), 10, buf,
&actualLength, 0);
if (actualLength < precision) {
zeroPad = precision-actualLength;
actualLength += zeroPad;
}
break;
case 's':
field = va_arg(args, char *);
if (field == (char *) NULL) {
field = "(NULL)";
}
actualLength = strlen(field);
if ((precision >= 0) && (precision < actualLength)) {
actualLength = precision;
}
pad = ' ';
break;
case 'c':
buf[0] = va_arg(args, int);
actualLength = 1;
pad = ' ';
break;
case 'F':
case 'f':
if (precision < 0) {
precision = 6;
} else if (precision > CVT_DBL_BUF_SIZE) {
precision = CVT_DBL_BUF_SIZE;
}
/*
* Just generate the digits and compute the total length
* here. The rest of the work will be done when the
* characters are actually output, below.
*/
#ifdef sun4
/*
* Varargs is not correctly implemented in gcc version 1.34
* for the sun4. This problem should be fixed in the next
* version of the compiler, and this code can then be
* deleted.
*/
{
union {
long i[2];
double d;
} u;
u.i[0] = va_arg(args, long);
u.i[1] = va_arg(args, long);
actualLength = CvtFtoA(u.d, CVT_DBL_BUF_SIZE,
precision, &point, &sign, field, &fpError);
}
#else
actualLength = CvtFtoA(va_arg(args, double), CVT_DBL_BUF_SIZE,
precision, &point, &sign, field, &fpError);
#endif
if (sign) {
prefix = "-";
actualLength += 1;
} else {
prefix = signChar;
actualLength += *prefix ? 1 : 0;
}
if (fpError) {
pad = ' ';
break;
}
if (point <= 0) {
actualLength += 1 - point;
}
if ((precision != 0) || (altForm)) {
actualLength += 1;
}
c = 'f';
break;
case 'E':
case 'e':
if (precision < 0) {
precision = 6;
} else if (precision > CVT_DBL_BUF_SIZE-1) {
precision = CVT_DBL_BUF_SIZE-1;
}
#ifdef sun4
/*
* Varargs is not correctly implemented in gcc version 1.34
* for the sun4. This problem should be fixed in the next
* version of the compiler, and this code can then be
* deleted.
*/
{
union {
long i[2];
double d;
} u;
u.i[0] = va_arg(args, long);
u.i[1] = va_arg(args, long);
actualLength = CvtFtoA(u.d, precision+1, -1,
&point, &sign, &buf[1], &fpError);
}
#else
actualLength = CvtFtoA(va_arg(args, double), precision+1, -1,
&point, &sign, &buf[1], &fpError);
#endif
if (fpError) {
pad = ' ';
field = &buf[1];
if (sign) {
prefix = "-";
actualLength += 1;
} else {
prefix = signChar;
actualLength += *prefix ? 1 : 0;
}
break;
}
eFromG:
/*
* Insert a decimal point after the first digit of the number.
* If no digits after decimal point, then don't print decimal
* unless in altForm.
*/
buf[0] = buf[1];
buf[1] = '.';
if ((precision != 0) || (altForm)) {
field = buf + precision + 2;
} else {
field = &buf[1];
}
/*
* Convert the exponent.
*/
*field = c;
field++;
point--; /* One digit before decimal point. */
if (point < 0) {
*field = '-';
point = -point;
} else {
*field = '+';
}
field++;
if (point < 10) {
*field = '0';
field++;
}
strcpy(field, CvtUtoA((unsigned) point, 10, expBuf, &i, 0));
actualLength = (field - buf) + i;
field = buf;
if (sign) {
prefix = "-";
actualLength += 1;
} else {
prefix = signChar;
actualLength += *prefix ? 1 : 0;
}
break;
case 'G':
case 'g': {
int eLength, fLength;
if (precision < 0) {
precision = 6;
} else if (precision > CVT_DBL_BUF_SIZE-1) {
precision = CVT_DBL_BUF_SIZE-1;
} else if (precision == 0) {
precision = 1;
}
#ifdef sun4
/*
* Varargs is not correctly implemented in gcc version 1.34
* for the sun4. This problem should be fixed in the next
* version of the compiler, and this code can then be
* deleted.
*/
{
union {
long i[2];
double d;
} u;
u.i[0] = va_arg(args, long);
u.i[1] = va_arg(args, long);
actualLength = CvtFtoA(u.d, precision,
-1, &point, &sign, &buf[1], &fpError);
}
#else
actualLength = CvtFtoA(va_arg(args, double), precision,
-1, &point, &sign, &buf[1], &fpError);
#endif
if (fpError) {
pad = ' ';
field = &buf[1];
if (sign) {
prefix = "-";
actualLength += 1;
} else {
prefix = signChar;
actualLength += *prefix ? 1 : 0;
}
break;
}
if (!altForm) {
for ( ; actualLength > 1; actualLength--) {
if (buf[actualLength] != '0') {
break;
}
}
}
if ((actualLength > 1) || altForm) {
eLength = actualLength + 5;
} else {
eLength = actualLength + 4;
}
if (point <= 0) {
fLength = actualLength + 2 - point;
} else {
fLength = actualLength;
if (point < actualLength) {
fLength += 1;
} else if (altForm) {
fLength = point + 1;
} else {
fLength = point;
}
}
/*
* Use "e" format if it results in fewer digits than "f"
* format, or if it would result in non-significant zeroes
* being printed. Remember that precision means something
* different in "e" and "f" (digits after decimal) than it
* does in "g" (significant digits).
*/
if ((eLength < fLength) || (point > precision)) {
c += 'E' - 'G';
precision = actualLength-1;
goto eFromG;
}
c = 'f';
field = &buf[1];
actualLength = fLength;
if (sign) {
prefix = "-";
actualLength += 1;
} else {
prefix = signChar;
actualLength += *prefix ? 1 : 0;
}
break;
}
case '%':
putc('%', stream);
charsPrinted += 1;
goto endOfField;
case 0:
return charsPrinted;
default:
putc(c, stream);
charsPrinted += 1;
goto endOfField;
}
/*
* Things get tricky if we want to pad with 0's and left justify.
*/
if (leftAdjust && pad == '0') {
if (c=='f' || c=='F' || c=='e' || c=='E' || c=='g' || c=='G') {
pad = ' ';
} else {
leftAdjust = FALSE;
}
}
/* Handle pad characters on the left. If the pad is '0', then
* padding goes after the prefix. Otherwise, padding goes before
* the prefix.
*/
if (!leftAdjust) {
if (pad == '0') {
for ( ; *prefix != 0; prefix++) {
putc(*prefix, stream);
charsPrinted += 1;
actualLength--;
minWidth--;
}
}
while (minWidth > actualLength) {
putc(pad, stream);
charsPrinted += 1;
minWidth --;
}
}
/*
* Output anything left in the prefix.
*/
minWidth -= actualLength;
for ( ; *prefix != 0; prefix++) {
putc(*prefix, stream);
charsPrinted += 1;
actualLength--;
}
/*
* Pad the digits to the right length with 0's.
*/
for (; zeroPad>0; zeroPad--) {
putc('0', stream);
charsPrinted += 1;
actualLength--;
}
/*
* "F" and "f" formats are handled specially here: output
* everything up to and including the decimal point.
*/
if (c == 'f' && !fpError) {
if (point <= 0) {
if (actualLength > 0) {
putc('0', stream);
charsPrinted += 1;
point++;
actualLength--;
}
if (actualLength > 0) {
charsPrinted += 1;
putc('.', stream);
actualLength--;
}
while ((point <= 0) && (actualLength > 0)) {
putc('0', stream);
charsPrinted += 1;
point++;
actualLength--;
}
} else {
while ((point > 0) && (actualLength > 0)) {
putc(*field, stream);
charsPrinted += 1;
field++;
point--;
actualLength--;
}
if (actualLength > 0) {
putc('.', stream);
charsPrinted += 1;
actualLength--;
}
}
}
/*
* Output the contents of the field (for "f" format, this is
* just the stuff after the decimal point).
*/
charsPrinted += actualLength;
for ( ; actualLength > 0; actualLength--, field++) {
putc(*field, stream);
}
/*
* Pad the right of the field, if necessary.
*/
while (minWidth > 0) {
putc(' ', stream);
charsPrinted += 1;
minWidth --;
}
endOfField: continue;
}
return charsPrinted;
}
@
1.20.1.1
log
@Initial branch for Sprite server.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.20 91/08/27 17:35:55 rab Exp Locker: rab $ SPRITE (Berkeley)";
@
1.19
log
@Changed printf to print Inf, NaN, and to put signs on these.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.18 90/10/11 15:14:09 shirriff Exp Locker: shirriff $ SPRITE (Berkeley)";
d26 2
@
1.18
log
@Modified left-adjust vs. 0 padding conflict to match ginger.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.17 90/10/08 17:04:52 shirriff Exp Locker: shirriff $ SPRITE (Berkeley)";
d200 11
d219 2
a220 2
strcpy(buf, "(INFINITY)");
return sizeof("(INFINITY)") - 1;
d224 2
a225 2
strcpy(buf, "(NaN)");
return sizeof("(NaN)") - 1;
d227 1
a230 11
* Take care of the sign.
*/
if (value < 0.0) {
*signPtr = TRUE;
value = -value;
} else {
*signPtr = FALSE;
}
/*
d623 7
a639 7
if (sign) {
prefix = "-";
actualLength += 1;
} else {
prefix = signChar;
actualLength += *prefix ? 1 : 0;
}
d676 7
d770 7
@
1.17
log
@Fix to handle (NaN) correctly.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.16 90/09/11 14:27:14 kupfer Exp Locker: shirriff $ SPRITE (Berkeley)";
d623 1
d673 1
d760 1
d830 1
a830 1
* Don't left adjust if we're padding the number only with 0's.
d832 6
a837 2
if (pad == '0') {
leftAdjust = FALSE;
@
1.16
log
@Use function prototypes. Lint.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.15 90/09/05 22:41:07 shirriff Exp Locker: kupfer $ SPRITE (Berkeley)";
d672 1
d758 1
@
1.15
log
@Added 'h' flag.
Fixed a bug with the wrong variable name, that caused printed hex
numbers to disappear sometimes.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.14 90/08/03 16:30:43 shirriff Exp $ SPRITE (Berkeley)";
d25 1
a190 1
extern double modf();
@
1.14
log
@Fixed a bunch of bugs in printf.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.13 89/09/12 11:42:15 douglis Exp $ SPRITE (Berkeley)";
d485 4
d535 1
a535 1
if (tmp < precision) {
@
1.13
log
@use isinf and isnan functions.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.12 89/08/04 16:05:13 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
d63 1
a63 1
CvtUtoA(i, base, buf, lengthPtr)
d72 1
d75 1
d118 1
a118 1
*p += 'a' - '9' - 1;
d129 1
a129 1
*p += 'a' - '9' - 1;
d391 1
d400 1
d432 1
d434 2
a435 1
actualLength = 0;
d447 5
a451 2
prefix = "+";
actualLength = 1;
d470 1
d495 1
d501 3
d505 5
a509 2
field = CvtUtoA((unsigned) i, 10, buf, &tmp);
actualLength += tmp;
d515 5
a519 1
if (altForm && (i != 0)) {
d523 1
a523 2
field = CvtUtoA((unsigned) i, 8, buf, &tmp);
actualLength += tmp;
d528 1
d530 5
a534 1
field = CvtUtoA((unsigned) i, 16, buf, &actualLength);
d557 5
a561 1
&actualLength);
d630 3
d704 1
a704 1
strcpy(field, CvtUtoA((unsigned) point, 10, expBuf, &i));
d710 3
d799 3
d820 7
d855 9
@
1.12
log
@more changes for omitted fpError arg. (done by jhh)
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.10 89/07/28 15:57:35 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
a191 1
int word;
d200 1
a200 6
{
union {
double d;
long l[2];
} u;
d202 2
a203 1
* Put the value into a union so we can check out the bits.
d205 8
a212 54
u.d = value;
/*
* Set up the indexes into u.l based on machine type.
*/
#ifdef ds3100
word = 1;
#else /* ds3100 */
word = 0;
#endif /* ds3100 */
/*
* An IEEE Std 754 double precision floating point number
* has the following format:
*
* 1 bit -- sign of Mantissa
* 11 bits -- exponent
* 52 bits -- Mantissa
*
* If the exponent has all bits set, the value is not a
* real number.
*
* If the Mantissa is zero then the value is infinity, which
* is the result of division by zero, or overflow.
*
* If the Mantissa is non-zero the value is not a number (NaN).
* NaN can be generated by dividing zero by itself, taking the
* logarithm of a negative number, etc.
*/
/*
* check the exponent
*/
if ((u.l[word] & 0x7ff00000) == 0x7ff00000) {
/*
* Set the error flag so the invoking function will know
* that something is wrong.
*/
*fpError = TRUE;
/*
* See if the Mantissa is zero.
*/
if ((u.l[word] & ~0xfff00000) == 0 && u.l[word ? 0 : 1] == 0) {
strcpy(buf, "(INFINITY)");
return sizeof("(INFINITY)") - 1;
} else {
strcpy(buf, "(NaN)");
return sizeof("(NaN)") - 1;
}
} else {
*fpError = FALSE;
}
d214 1
@
1.11
log
@temp change for ds3100 floating
@
text
@d679 1
a679 1
&point, &sign, &buf[1]);
d683 1
a683 1
&point, &sign, &buf[1]);
d760 1
a760 1
-1, &point, &sign, &buf[1], fpError);
@
1.10
log
@fixed bug with omitted argument
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.9 89/07/28 15:56:48 rab Exp Locker: douglis $ SPRITE (Berkeley)";
d192 1
d213 10
d244 1
a244 1
if ((u.l[0] & 0x7ff00000) == 0x7ff00000) {
d254 1
a254 1
if ((u.l[0] & ~0xfff00000) == 0 && u.l[1] == 0) {
@
1.9
log
@ifdefs for sun4 for varargs (c.i. by FD)
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.8 89/06/16 14:14:45 ouster Exp Locker: rab $ SPRITE (Berkeley)";
d749 1
a749 1
-1, &point, &sign, &buf[1]);
d753 1
a753 1
-1, &point, &sign, &buf[1]);
@
1.8
log
@Zero-precision wasn't handled right for strings.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.7 89/05/25 05:50:03 rab Exp $ SPRITE (Berkeley)";
d605 15
d621 4
d627 1
d651 20
d673 1
d731 21
d754 2
@
1.7
log
@Fixed CvtFtoA to properly handle infinity and NaN.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.6 89/05/17 14:32:46 rab Exp $ SPRITE (Berkeley)";
d580 1
a580 1
if ((precision > 0) && (precision < actualLength)) {
@
1.6
log
@Added `+' modifier to print out the sign.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: /sprite/src/lib/c/stdio/RCS/vfprintf.c,v 1.5 88/10/23 15:39:51 ouster Exp Locker: rab $ SPRITE (Berkeley)";
d170 1
a170 1
CvtFtoA(value, numDigits, afterPoint, pointPtr, signPtr, buf)
d184 3
a191 1
d196 59
a254 1
d440 1
d591 1
a591 1
d606 5
a610 2
actualLength = CvtFtoA(va_arg(args, double),
CVT_DBL_BUF_SIZE, precision, &point, &sign, field);
d631 1
a631 1
(void) CvtFtoA(va_arg(args, double), precision+1, -1,
d633 3
a635 1
d643 1
a643 1
d678 1
a678 1
d692 3
d761 1
a761 1
d794 1
a794 1
if (c == 'f') {
d842 1
a842 1
@
1.5
log
@Change position of "#" in formats, permit flags in any order.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: vfprintf.c,v 1.4 88/07/25 13:12:35 ouster Exp $ SPRITE (Berkeley)";
d390 1
a390 1
d407 1
d418 3
a458 1
actualLength = 0;
@
1.4
log
@Lint.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: vfprintf.c,v 1.3 88/07/21 09:36:16 ouster Exp $ SPRITE (Berkeley)";
d410 11
a420 3
if (c == '-') {
leftAdjust = TRUE;
format++;
a421 5
};
while (c == '0') {
pad = '0';
format++;
c = *format;
a441 5
format++;
c = *format;
}
if (c == '#') {
altForm = TRUE;
@
1.3
log
@Change from _doprnt to vfprintf.
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: vfprintf.c,v 1.2 88/06/17 17:42:51 ouster Exp $ SPRITE (Berkeley)";
d20 5
a24 4
#include "ctype.h"
#include "stdio.h"
#include "string.h"
#include "varargs.h"
@
1.2
log
@Accidentally used old Cvt_FtoA routine.
@
text
@d2 1
a2 1
* _doprnt.c --
d4 1
a4 1
* Source code for the "_doprnt" library procedure.
d17 1
a17 1
static char rcsid[] = "$Header: _doprnt.c,v 1.1 88/06/10 16:23:36 ouster Exp $ SPRITE (Berkeley)";
d324 1
a324 1
* _doprnt --
d327 2
a328 2
* formatted information. It is called by printf, fprintf, and
* sprintf.
d341 2
a342 1
_doprnt(format, args, stream)
d346 1
a346 1
va_list *args; /* Variable number of values to be formatted
a347 1
register FILE *stream; /* Where to output formatted results. */
d424 1
a424 1
minWidth = va_arg(*args, int);
d437 1
a437 1
precision = va_arg(*args, int);
d461 1
a461 1
i = va_arg(*args, int);
d473 1
a473 1
i = va_arg(*args, int);
d484 1
a484 1
i = va_arg(*args, int);
d507 1
a507 1
field = CvtUtoA(va_arg(*args, unsigned), 10, buf,
d512 1
a512 1
field = va_arg(*args, char *);
d524 1
a524 1
buf[0] = va_arg(*args, int);
d543 1
a543 1
actualLength = CvtFtoA(va_arg(*args, double),
d565 1
a565 1
(void) CvtFtoA(va_arg(*args, double), precision+1, -1,
d622 1
a622 1
actualLength = CvtFtoA(va_arg(*args, double), precision,
@
1.1
log
@Initial revision
@
text
@d17 1
a17 1
static char rcsid[] = "$Header: atoi.c,v 1.1 88/04/28 17:20:23 ouster Exp $ SPRITE (Berkeley)";
d622 1
a622 1
actualLength = Cvt_FtoA(va_arg(*args, double), precision,
@